﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace Scommesse.Model
{
    [Serializable]
    public class Competizione : ICompetizione
    {
        private readonly List<IEvento> _eventi;
        private readonly string _nome;
        private DateTime _dataFine = DateTime.MaxValue;
        private DateTime _dataInizio = DateTime.MinValue;

        public Competizione(string nome, ICategoria categoria)
        {
            if (nome == null) throw new ArgumentNullException("nome");
            _nome = nome;
            _eventi = new List<IEvento>();
            Categoria = categoria;
        }

        public Competizione(string nome, ICategoria categoria, DateTime dataInizio, DateTime dataFine)
            : this(nome, categoria)
        {
            _dataInizio = dataInizio;
            if (dataFine.CompareTo(DateTime.Now) < 0)
                throw new ArgumentException("Competizione terminata");
            _dataFine = dataFine;
        }

        public string Nome
        {
            get { return _nome; }
        }

        public ICategoria Categoria { get; private set; }

        public List<IEvento> Eventi
        {
            get { return _eventi; }
        }

        public void CheckDate(IEvento evento)
        {
            if (_dataInizio.CompareTo(evento.DataOra) > 0)
                throw new ArgumentException("data evento non coincide con quella della competizione");
            if (_dataFine.CompareTo(evento.DataOra) < 0)
                throw new ArgumentException("data evento non coincide con quella della competizione");
        }

        public IEvento AddEvento(string competitoreA, string competitoreB, DateTime dataOra)
        {
            var evento = new Evento(competitoreA, competitoreB, dataOra, this);
            if (_eventi.Contains(evento))
                throw new Exception("l'evento esiste già");
            CheckDate(evento);
            _eventi.Add(evento);
            return evento;
        }

        public IEvento AddEvento(Guid id, string competitoreA, string competitoreB, DateTime dataOra, StatoEvento stato)
        {
            var evento = new Evento(id, competitoreA, competitoreB, dataOra, stato, this);
            if (_eventi.Contains(evento))
                throw new Exception("l'evento esiste già");
            CheckDate(evento);
            _eventi.Add(evento);
            return evento;
        }

        public void RemoveEvento(string competitoreA, string competitoreB, DateTime dataOra)
        {
            _eventi.Remove(new Evento(competitoreA, competitoreB, dataOra, this));
        }

        public DateTime DataInizio()
        {
            return _dataInizio;
        }

        public DateTime DataFine()
        {
            return _dataFine;
        }

        public IEvento GetEvento(String compA, String compB, DateTime data)
        {
            return Eventi.FirstOrDefault(evento => evento.Equals(new Evento(compA, compB, data, this)));
        }
        
        public override bool Equals(object obj)
        {
            if (obj == null || GetType() != obj.GetType())
                return false;
            Competizione competizione = (Competizione)obj;
            return (Nome.ToLower().Equals(competizione.Nome.ToLower()) && Categoria.Equals(competizione.Categoria));
        }

        public override int GetHashCode()
        {
            return GetType().GetHashCode();
        }
    }
}